package com.whfc.common.auth;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.whfc.common.util.DateUtil;

import java.util.Date;

/**
 * JWT工具类`
 *
 * @author xuguocheng
 * @date 2018-08-03
 */
public class JwtUtils {

    /**
     * 应用类型
     */
    private static final String APP_TYPE = "app_type";

    /**
     * 登录方式
     */
    private static final String LOGIN_METHOD = "login_method";

    /**
     * 用户标识
     */
    private static final String USER = "user";

    /**
     * 版本号key
     */
    private static final String VERSION = "ver";

    /**
     * 计算jwt授权token
     *
     * @param payLoad
     * @param secret
     * @return
     */
    public static String sign(JwtPayLoad payLoad, String secret) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            String sign = JWT.create()
                    .withClaim(APP_TYPE, payLoad.getAppType())
                    .withClaim(LOGIN_METHOD, payLoad.getLoginMethod())
                    .withClaim(USER, payLoad.getUser())
                    .withClaim(VERSION, payLoad.getVer())
                    .withExpiresAt(payLoad.getExpireAt())
                    .sign(algorithm);
            return sign;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 验证jwt
     *
     * @param token
     * @param payLoad
     * @param secret
     * @return
     * @throws JWTVerificationException
     */
    public static void verify(String token, JwtPayLoad payLoad, String secret) throws JWTVerificationException {
        Algorithm algorithm = Algorithm.HMAC256(secret);
        JWTVerifier verifier = JWT.require(algorithm)
                .withClaim(USER, payLoad.getUser())
                .withClaim(VERSION, payLoad.getVer())
                .build();
        verifier.verify(token);
    }

    /**
     * 从token中获取用户名
     *
     * @param token
     * @return
     */
    public static JwtPayLoad getPayLoad(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            String appType = jwt.getClaim(APP_TYPE).asString();
            String loginMethod = jwt.getClaim(LOGIN_METHOD).asString();
            String user = jwt.getClaim(USER).asString();
            Long version = jwt.getClaim(VERSION).asLong();
            Date expiresAt = jwt.getExpiresAt();

            JwtPayLoad payLoad = new JwtPayLoad();
            payLoad.setAppType(appType);
            payLoad.setLoginMethod(loginMethod);
            payLoad.setUser(user);
            payLoad.setVer(version);
            payLoad.setExpireAt(expiresAt);
            return payLoad;

        } catch (Exception e) {
            return null;
        }
    }

    public static void main(String[] args) {

        String user = "xugc";
        String secret = "4355c41f986cd9cc193014db274fde0f0dfbe20d4d4a1349e02badd0";

        JwtPayLoad payLoad = new JwtPayLoad();
        payLoad.setAppType("cms");
        payLoad.setLoginMethod("user_pass_login");
        payLoad.setUser(user);
        payLoad.setVer(100L);
        payLoad.setExpireAt(DateUtil.addHours(new Date(), 2));

        System.out.println("payLoad:" + payLoad);

        String sign = JwtUtils.sign(payLoad, secret);
        System.out.println("sign:" + sign);

        //TimeUnit.MINUTES.sleep(2);

        try {
            JwtUtils.verify(sign, payLoad, secret);
        } catch (JWTVerificationException ex) {
            ex.printStackTrace();
        }

        JwtPayLoad payLoad1 = JwtUtils.getPayLoad(sign);
        System.out.println("payLoad:" + payLoad1);
    }
}